package cn.tedu.reflect;

import java.io.ObjectInputStream;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;

public class TextDemo {
    public static void main(String[] args) throws InstantiationException, IllegalAccessException, InvocationTargetException {
        //
        Person p=new Person("小倩",18);
       /* p.setName("小倩");
        p.setAge(18);*/
        //调用方法返回克隆对象
        Person p1 = (Person) clone(p);
        System.out.println(p1.getName()+","+p1.getAge());
    }

    //可以接收任意类型的对象进行克隆
    public static Object clone(Object obj) throws IllegalAccessException, InstantiationException, InvocationTargetException {
        //1.获取字节码对象
        Class<Object> clz = (Class<Object>) obj.getClass();
        //2.获取实例对象（克隆对象）
        //保证一定可以获取构造方法
        Constructor c = (Constructor<Object>)
                clz.getDeclaredConstructors()[0];
        //把构造方法的参数列表的所有参数类型放到数组中
        Class[] cs = (Class<Object>[]) c.getParameterTypes();
        //新建数组存储要给参数类型赋予的值
        Object[] os=new Object[cs.length];
        //遍历数组
        for(int i=0;i<cs.length;i++){
            //
            if(cs[i].isPrimitive()){//判断是否是基本数据类型
                //
                if((cs[i]==byte.class)||cs[i]==short.class||cs[i]==int.class||cs[i]==long.class){
                     os[i]=0;
                }else if(cs[i]==char.class){
                    os[i]='\u0000';
                }else if(cs[i]==float.class||cs[i]==double.class){
                    os[i]=0.0F;
                }else{
                    os[i]=false;
                }
            }else{//引用数据类型

            }
        }
        //给构造方法进行赋值执行构造方法返回实例对象
        Object o = c.newInstance(os);

        //3.获取原对象的所有的属性
        Field[] fields = clz.getDeclaredFields();
        //4.把原对象所有的属性值赋值给实例对象（克隆对象）
        //遍历数组
        for(Field fs:fields){
            //暴力破解
            fs.setAccessible(true);
            //获取原对象的属性值
            Object value = fs.get(obj);
            //把原对象的属性值赋值给实例对象（克隆对象）
            fs.set(o,value);
        }
        //返回克隆对象
        return o;


        //执行无参构造返回实例对象
       /* Object o = clz.newInstance();
        //3.获取原对象的所有的属性
        Field[] fields = clz.getDeclaredFields();
        //4.把原对象所有的属性值赋值给实例对象（克隆对象）
        //遍历数组
        for(Field fs:fields){
            //暴力破解
            fs.setAccessible(true);
            //获取原对象的属性值
            Object value = fs.get(obj);
            //把原对象的属性值赋值给实例对象（克隆对象）
            fs.set(o,value);
        }
        //返回克隆对象
        return o;*/
    }
}

//
class Person{
    private String name;
    private int age;

    //有参构造
    public Person(String name,int age){
        this.name=name;
        this.age=age;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }
}
